﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
using System.Xml;
using Microsoft.SharePoint;

namespace SPProfileData
{
    class Importer
    {
        private static long total;
        private static long start;
        public static void Import(string url, string filename)
        {
            try
            {
                using (SPSite site = new SPSite(url))
                {
                    UserProfileManager userProfileManager = new UserProfileManager(ServerContext.GetContext(site));
                    XmlDocument xml = new XmlDocument();
                    xml.Load(filename);

                    int count = 0;
                    var nodes = xml.SelectNodes("//User");
                    total = nodes.Count;
                    Console.Out.WriteLine("Profiles to import: {0}", total);
                    start = DateTime.Now.Ticks;
                    foreach (XmlNode user in nodes)
                    {
                        count++;
                        if (count % 1000 == 0)
                        {
                            PrintProgress(count);
                        }
                        try
                        {
                            UserProfile profile = userProfileManager.GetUserProfile(user.Attributes["AccountName"].Value.ToString());
                            foreach (XmlNode p in user.ChildNodes)
                            {
                                if (CanUpdate(p, profile))
                                {
                                    try
                                    {
                                        switch (p.Attributes["Type"].Value.ToString())
                                        {
                                            case "List":
                                                foreach (XmlNode e in p.ChildNodes)
                                                {
                                                    profile[p.Attributes["Name"].Value.ToString()].Add(e.InnerText);
                                                }
                                                break;
                                            case "date":
                                                profile[p.Attributes["Name"].Value.ToString()].Value = DateTime.Parse(p.InnerText);
                                                break;
                                            default:
                                                profile[p.Attributes["Name"].Value.ToString()].Value = p.InnerText;
                                                break;
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        if (!p.Attributes["Name"].Value.ToString().Equals("manager", StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            Console.Out.WriteLine(profile["accountname"].Value.ToString() + " :: " + p.Attributes["Name"].Value.ToString() + " :: " + e.Message);
                                        }
                                    }
                                }
                            }
                            profile.Commit();
                        }
                        catch (Exception e)
                        {
                            Console.Out.WriteLine(user.Attributes["UNumber"].Value.ToString() + " :: " + e.Message);
                        }
                    }

                    Console.Out.WriteLine("Done");
                }
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.ToString());
            }
        }

        private static void PrintProgress(int count)
        {
            var diff = DateTime.Now.Ticks - start;
            var remaining = total - count;

            var perEach = diff / count;
            var r = remaining * perEach;

            var remainingTime = new DateTime(DateTime.Now.Ticks + r);
            Console.Out.WriteLine("Processed {0} profiles. Estimated completion {1}", count, remainingTime.ToShortTimeString());
        }

        private static bool CanUpdate(XmlNode p, UserProfile p2)
        {
            var name = p.Attributes["Name"].Value.ToString();
            return p2.ProfileManager.Properties.GetPropertyByName(name) != null && p2[name].Property.IsAdminEditable;
        }
    }
}
